package com.dsz.apibackend.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dsz.apibackend.common.ErrorCode;
import com.dsz.apibackend.exception.BusinessException;
import com.dsz.apibackend.mapper.UserMapper;
import com.dsz.apibackend.model.dto.user.UserLoginRequest;
import com.dsz.apibackend.model.dto.user.UserRegisterRequest;
import com.dsz.apibackend.model.vo.UserVO;
import com.dsz.apibackend.service.UserService;
import com.dsz.apicommon.model.domain.User;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;

import javax.servlet.http.HttpServletRequest;

import static com.dsz.apibackend.constants.UserConstant.USER_LOGIN_STATE;
import static java.util.regex.Pattern.compile;

/**
 * @author dushangzhi
 * @description 针对表【user(用户)】的数据库操作Service实现
 * @createDate 2024-03-14 11:01:20
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {
    /**
     * 盐值
     */
    private static final String SALT = "dushangzhi";

    /**
     * 用户登录
     */
    @Override
    public UserVO userLogin(UserLoginRequest userLoginRequest, HttpServletRequest request) {
        //1.校验参数：请求对象、用户名、密码
        if (userLoginRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        String userAccount = userLoginRequest.getUserAccount();
        String userPassword = userLoginRequest.getUserPassword();
        //非空
        if (StringUtils.isAnyBlank(userAccount, userPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //账户长度不小于4位
        if (userAccount.length() < 4) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账户长度过小");
        }
        //账户不包含特殊字符
        String regEx = "\\pP|\\pS|\\s+";
        String str = compile(regEx).matcher(userAccount).replaceAll("").trim();
        if (!str.equals(userAccount)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账户包含特殊字符");
        }
        //密码不小于8位
        if (userPassword.length() < 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码小于8位");
        }
        //2.从数据库中查询用户名
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUserAccount, userAccount);
        User user = this.getOne(queryWrapper);
        if (user == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR, "用户不存在");
        }
        //3.比对密码
        String password = user.getUserPassword();
        String s = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
        if (!password.equals(s)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码不正确");
        }
        //4.存储用户信息到session
        UserVO safetyUser = this.getSafetyUser(user);
        request.getSession().setAttribute(USER_LOGIN_STATE, safetyUser);
        //5.返回脱敏后的用户信息
        return safetyUser;
    }

    /**
     * 用户注册
     */
    @Override
    public Long userRegister(UserRegisterRequest userRegisterRequest) {
        //1.校验参数
        if (userRegisterRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //非空
        String userAccount = userRegisterRequest.getUserAccount();
        String userPassword = userRegisterRequest.getUserPassword();
        String checkPassword = userRegisterRequest.getCheckPassword();
        if (StringUtils.isAnyBlank(userAccount, userPassword, checkPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //账户长度不小于4位
        if (userAccount.length() < 4) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账户长度过小");
        }
        //账户不包含特殊字符
        String regEx = "\\pP|\\pS|\\s+";
        String str = compile(regEx).matcher(userAccount).replaceAll("").trim();
        if (!str.equals(userAccount)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账户包含特殊字符");
        }
        //密码不小于8位
        if (userPassword.length() < 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码小于8位");
        }
        //密码和校验密码是否相同
        if (!userPassword.equals(checkPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次输入密码不一致");
        }
        //2.检查账户是否已存在
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUserAccount, userAccount);
        long count = this.count(queryWrapper);
        if (count > 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账户已存在");
        }
        //3.加密密码
        String s = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());
        //4.生成accessKey、secretKey
        String accessKey = DigestUtil.md5Hex(SALT + userAccount + RandomUtil.randomNumbers(5));
        String secretKey = DigestUtil.md5Hex(SALT + userAccount + RandomUtil.randomNumbers(8));
        //5.将用户数据存储到数据库
        User user = new User();
        user.setUserAccount(userAccount);
        user.setUserPassword(s);
        user.setAccessKey(accessKey);
        user.setSecretKey(secretKey);
        boolean save = this.save(user);
        if (!save) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "插入数据库失败");
        }
        //5.返回用户id
        return user.getId();
    }

    /**
     * 退出登录
     */
    @Override
    public boolean userLogout(HttpServletRequest request) {
        //1.校验参数
        if (request == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //2.检查当前是否登录
        Object attribute = request.getSession().getAttribute(USER_LOGIN_STATE);
        if (attribute == null) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "未登录");
        }
        //3.删除session
        request.getSession().removeAttribute(USER_LOGIN_STATE);
        return true;
    }

    /**
     * 获取当前登录用户
     */
    @Override
    public UserVO getCurrentUser(HttpServletRequest request) {
        //1.校验参数
        if (request == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //2.检查是否登录
        Object attribute = request.getSession().getAttribute(USER_LOGIN_STATE);
        UserVO userVO = (UserVO) attribute;
        if (userVO == null || userVO.getId() == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR);
        }
        //3.返回用户信息
        User user = this.getById(userVO.getId());
        UserVO currentUser = new UserVO();
        BeanUtils.copyProperties(user, currentUser);
        return currentUser;
    }

    /**
     * 用户脱敏
     */
    public UserVO getSafetyUser(User user) {
        if (user == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return userVO;
    }
}




